#pragma once
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <functional>
#include <set>
#include <vector>
#include <cassert>
#include "log.h"
namespace sylar
{
    class TimerManager;
    using func_t = std::function<void()>;
    class Timer : public std::enable_shared_from_this<Timer>  //调用shared from this（）在内部获取sharedptr
    {
        friend TimerManager;
    private:
        bool _is_recurring;                                         // 是否重复使用
        uint64_t _ms;                                              // 触发相对时间
        std::chrono::time_point<std::chrono::system_clock> _clock; // 触发绝对时间
        func_t _func; //时间到时执行的回执函数
        TimerManager* _manager; //回指指针指向我的管理者
    private:
        //构造函数
        Timer(uint64_t ms,func_t func,bool is_recurring,TimerManager* manager);
        //Compare()实现两个timer类的比较
        struct Compare{
            //实现 < 比较逻辑
            bool operator()(const std::shared_ptr<Timer>& t1, const std::shared_ptr<Timer>& t2) const;
        };
    public:
        bool cancel(); //从时间堆中删除
        bool refresh(); //刷新时间
        bool reset(uint64_t ms,bool if_fromnow); //重设超时时间
    };

    class TimerManager
    {
        friend Timer;
    private:
        std::shared_mutex _mtx; //实现高性能共享读，排他写
        std::set<std::shared_ptr<Timer>,Timer::Compare> _timers; //set树实现小堆
        // 在下次getNextTime()执行前 onTimerInsertedAtFront()是否已经被触发了 -> 在此过程中 onTimerInsertedAtFront()只执行一次。防止重复调用
        bool _tickled = false;
        //_tickled是一个标志：
        //用于指示是否需要在定时器插入到时间堆的前端时触发额外的处理操作，例如唤醒一个等待的线程或进行其他管理操作。

        //上次检查系统时间是否回退 的 绝对时间（用于检查系统时间是否回退的核心）
        std::chrono::time_point<std::chrono::system_clock> _lastclock;

    public:
        TimerManager();
        virtual ~TimerManager(); //保证多态下正确析构
        //添加timer到小堆中
        std::shared_ptr<Timer> addTimer(uint64_t ms,func_t func,bool is_recurring);
        //添加条件timer到小堆中
        std::shared_ptr<Timer> addCondTimer(uint64_t ms,func_t func,std::weak_ptr<void> weak_condition,bool is_recurring);
        //weak_condtion作为一个弱指针，其绑定一个强智能指针std::shared_ptr,如果其存在则weak_condition.lock()如果否则失败

        //拿到堆中最近的超时时间
        uint64_t getNextTimer();

        //取出所有的超时回调函数
        void getExpiredfunc(std::vector<func_t>& func_v);

        //检查堆中是否有Timer

        bool hasTimer();
    protected:
        virtual void onTimerInsertAtFront(){}; //当一个Timer被添加到最前面时调用该函数
        void addTimer(std::shared_ptr<Timer> timer);
    private:
        //检测是否发生时间回滚
        bool detectClockRollover();

    };
}
